
using OhioState.Graphics;
using OhioState.Graphics.Proxy;
using Tao.OpenGl;

namespace OhioState.Graphics.OpenGL
{
    public class BoxOutlineGL : IDrawable
    {
        #region Public Properties
        private BoundingBox _bBox;
        public IBoundingVolume BoundingVolume
        {
            get { return _bBox; }
            set
            {
                BoundingBox bBox = value as BoundingBox;
                if (bBox != null)
                {
                    _bBox = (BoundingBox)bBox.Clone();
                }
            }
        }

        private int _drawablePosition;
        public int DrawablePosition
        {
            get { return _drawablePosition; }
            set { _drawablePosition = value; }
        }
       
        private bool _drawBackEdges = true;
        public bool DrawBackEdges
        {
            get { return _drawBackEdges; }
            set { _drawBackEdges = value; }
        }
        private bool _drawFrontEdges = true;
        public bool DrawFrontEdges
        {
            get { return _drawFrontEdges; }
            set { _drawFrontEdges = value; }
        }
        private IMaterial _material;
        public IMaterial Material
        {
            get { return _material; }
            set { _material = value; }
        }
        //
        // TODO: Make this part of the material.
        //
        //private float _lineWidth = 1.0f;
        //public float LineWidth
        //{
        //    get { return _lineWidth; }
        //    set { _lineWidth = value; }
        //}
        ////private OSUColor _color;
        ////public OSUColor Color
        ////{
        ////    get { return _color; }
        ////    set { _color = value; }
        ////}
        //private ushort _lineStipple;
        //public ushort LineStipple
        //{
        //    get { return _lineStipple; }
        //    set { _lineStipple = value; }
        //}
        #endregion Public Properties

        public BoxOutlineGL(BoundingBox bBox)
        {
            _bBox = bBox;
        }
        public void Update(IRenderPanel panel)
        {
        }
        public void Render(IRenderPanel panel)
        {
            if (!_drawFrontEdges && !_drawBackEdges)
            {
                return;
            }
            bool culling = true;
            if (_drawBackEdges && _drawFrontEdges)
            {
                culling = false;
            }
            bool bFront = true;
            if (culling)
            {
                bFront = _drawFrontEdges;
            }

            Gl.glPushAttrib(Gl.GL_POLYGON_BIT | Gl.GL_LINE_BIT | Gl.GL_CURRENT_BIT);
            if (culling)
            {
                Gl.glEnable(Gl.GL_CULL_FACE);
                Gl.glFrontFace(Gl.GL_CCW);
                Gl.glCullFace(bFront ? Gl.GL_BACK : Gl.GL_FRONT);
            }
            //
            // TODO - Make this part of the Material.
            //
            Gl.glPolygonMode(Gl.GL_FRONT_AND_BACK, Gl.GL_LINE);
            //Gl.glColor4f(_color.R, _color.G, _color.B, _color.A);
            //Gl.glEnable(Gl.GL_LINE_STIPPLE);
            //Gl.glLineStipple(4, (short)_lineStipple);
            //Gl.glLineWidth(_lineWidth);

            _material.MakeActive(panel);

            drawEdges();

            Gl.glPopAttrib();
            //
            // TODO - Make this part of the Material.
            //
            Gl.glPolygonMode(Gl.GL_FRONT_AND_BACK, Gl.GL_FILL);
            Gl.glDisable(Gl.GL_CULL_FACE);
            //Gl.glDisable(Gl.GL_LINE_STIPPLE);
            _material.Deactivate(panel);
        }
        private void drawEdges()
        {
            float x0, y0, z0, x1, y1, z1;
            x0 = _bBox.LowerLeft[0]; y0 = _bBox.LowerLeft[1]; z0 = _bBox.LowerLeft[2];
            x1 = _bBox.UpperRight[0]; y1 = _bBox.UpperRight[1]; z1 = _bBox.UpperRight[2];

            Gl.glBegin(Gl.GL_QUADS);
                // face 0
                Gl.glVertex3f(x0, y0, z0); Gl.glVertex3f(x0, y0, z1); Gl.glVertex3f(x0, y1, z1); Gl.glVertex3f(x0, y1, z0);
                // face 1
                Gl.glVertex3f(x1, y0, z0); Gl.glVertex3f(x1, y1, z0); Gl.glVertex3f(x1, y1, z1); Gl.glVertex3f(x1, y0, z1);
                // face 2
                Gl.glVertex3f(x0, y0, z0); Gl.glVertex3f(x1, y0, z0); Gl.glVertex3f(x1, y0, z1); Gl.glVertex3f(x0, y0, z1);
                // face 3
                Gl.glVertex3f(x0, y1, z0); Gl.glVertex3f(x0, y1, z1); Gl.glVertex3f(x1, y1, z1); Gl.glVertex3f(x1, y1, z0);
                // face 4
                Gl.glVertex3f(x0, y0, z0); Gl.glVertex3f(x0, y1, z0); Gl.glVertex3f(x1, y1, z0); Gl.glVertex3f(x1, y0, z0);
                // face 5
                Gl.glVertex3f(x0, y0, z1); Gl.glVertex3f(x1, y0, z1); Gl.glVertex3f(x1, y1, z1); Gl.glVertex3f(x0, y1, z1);
            Gl.glEnd();
        }
    }
}
